<template>
    <div>
        <div id="qrcode" style="display: none;"></div>
        <canvas ref="qrcodeRef"></canvas>
    </div> 
</template>
<script setup lang="ts">
import {ref,onMounted,nextTick,reactive,computed} from "vue";
import QRCode from "qrcodejs2-fix"
/*
    @description 父组件传参
    @params QRCodeOption 原有的QRCode参数,
            如text:必传，
            其他如width，height，colorDark, colorLight,correctLevel为选填
    @params bgOption 背景传参，url是地址,opacity是不透明度，0是全透明，1是完全不透明,color:透明度的颜色
    @params logoOption 中心logo传参，url是地址，opacity是不透明度，0是全透明，1是完全不透明,color:透明度的颜色
*/
const props=defineProps<{
    QRCodeOption:Record<'text',string>&Record<string,any>, 
    bgOption?:{
        url:string,
        opacity?:number,
        color?:string
    },
    logoOption?:{
        url:string,
        opacity?:number,
        color?:string
    },
}>()

const qrcodeRef=ref(null)

type TImgType='bg'|'logo'

interface IPromiseImg{
    type:TImgType,
    dom:HTMLImageElement
}

// 需要加载的图片数组
const imgArr=computed(()=>{
    const arr:{
        type:TImgType,
        url:string
    }[]=[];
    const {bgOption,logoOption}=props
    bgOption.url&&arr.push({
        type:'bg',
        url:bgOption.url
    });
    logoOption.url&&arr.push({
        type:'logo',
        url:logoOption.url
    });
    return arr
})

onMounted(()=>{
    const {QRCodeOption,bgOption,logoOption}=props
    nextTick(()=>{
        // 生成二维码
        const qrcode = new QRCode("qrcode", {
           ...QRCodeOption
        });
        // 获取二维码图片
        const elImg=qrcode._el.getElementsByTagName('img')[0]
        // 设置实际canvas二维码宽高
        const {width=128,height=128}=QRCodeOption
        qrcodeRef.value.width=width;
        qrcodeRef.value.height=height;
        // 获取上下文对象
        const ctx=qrcodeRef.value.getContext('2d')
        // 清除画布
        ctx.clearRect(0,0,width,height);
        // 图片加载的propmise
        const promiseAll:Promise<IPromiseImg>[]=[]
        // 设置需要加载的图片数组
        imgArr.value.forEach((item)=>{
            const promiseEach=new Promise<IPromiseImg>((resolve,reject)=>{
                const image=new Image();
                image.setAttribute('crossOrigin', 'Anonymous')
                image.src=item.url;
                image.onload=(()=>{
                    resolve({
                        dom:image,
                        type:item.type
                    })
                })
                image.onerror=(()=>{
                    reject('图片加载错误')
                })
            })
            promiseAll.push(promiseEach)
        })

        // 所有图片加载完毕了
        Promise.all(promiseAll).then((imgList)=>{
            // 绘制二维码
            ctx.drawImage(elImg,0,0,width,height)
            // 是否有背景图
            if(bgOption&&bgOption.url){
                // 设置属性
                ctx.fillStyle=bgOption.color??'#fff'
                ctx.globalAlpha=bgOption.opacity??0.5
                // 取值
                const findItem=imgList.find(item=>item.type==='bg')
                // 画背景图
                ctx.drawImage(findItem.dom,0,0,width,height)
            }
            // 是否有logo
            if(logoOption&&logoOption.url){
                ctx.fillStyle=logoOption.color??'#fff'
                ctx.globalAlpha=logoOption.opacity??1;
                 // 取值
                 const findItem=imgList.find(item=>item.type==='logo')
                // 取中心值
                const center=(width-width/5)/2
                // 画背景图
                ctx.drawImage(findItem.dom,center,center,width/5,height/5)
            }
        }) 
    })
})

</script>